.include "record-def.s"
.include "linux.s"

.section .data
input_file_name:
    .ascii "test.dat\0"

output_file_name:
    .ascii "testout.dat\0"

.section .bss
.lcomm record_buffer, RECORD_SIZE

# 局部变量的的栈偏移量
.equ ST_INPUT_DESCRIPTOR, -8
.equ ST_OUTPUT_DESCRIPTOR, -16

.section .text
.globl _start
_start:
    # 复制栈指针并为局部变量分配空间
    mov     %rsp, %rbp
    sub     $16, %rsp

    # 打开用于读取的文件
    mov     $SYS_OPEN, %rax
    mov     $input_file_name, %rbx
    mov     $0, %rcx
    mov     $0666, %rdx
    int     $LINUX_SYSCALL

    mov     %rax, ST_INPUT_DESCRIPTOR(%rbp)


    # 检测%rax是否为负值
    # 如果是非负值，那么程序将继续处理
    # 否则将处理负数对应的错误情况
    cmp     $0, %rax
    jg      continue_proccessing

    # 发送错误信息
    .section .data
no_open_file_code:
    .ascii  "0001: \0"
no_open_file_msg:
    .ascii "can't open input file\0"
    .section .text
    push    $no_open_file_msg
    push    $no_open_file_code
    call    error_exit


continue_proccessing:

    # 打开用于写入的文件
    mov     $SYS_OPEN, %rax
    mov     $output_file_name, %rbx
    mov     $0101, %rcx
    mov     $0666, %rdx
    int     $LINUX_SYSCALL

    mov     %rax, ST_OUTPUT_DESCRIPTOR(%rbp)

loop_begin:
    push    ST_INPUT_DESCRIPTOR(%rbp)
    push    $record_buffer
    call    read_record
    add     $16, %rsp

    # 返回读取的字节数，如果字节数与我们请求的字节数不同，
    # 说明已经到达文件结束处或出现错误，我们就要退出。
    cmp     $RECORD_SIZE, %rax
    jne     loop_end

    # 递增年龄
    incl    (record_buffer + RECORD_AGE)

    # 写记录
    push    ST_OUTPUT_DESCRIPTOR(%rbp)
    push    $record_buffer
    call    write_record
    add     $16, %rsp

    jmp     loop_begin

loop_end:
    # 输出一个换行符以优化显示。
    push    ST_OUTPUT_DESCRIPTOR(%rbp)
    call    write_newline
    add     $8, %rsp
    # 退出
    mov     $SYS_EXIT, %rax
    mov     $0, %rbx
    int     $LINUX_SYSCALL
